home *** CD-ROM | disk | FTP | other *** search
/ Chip 1999 October / CHIP_CD_1999_10_PL.iso / offline / hardware / Bump_mapping / MatroxRain - CHIP / rain.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-04  |  30.7 KB  |  1,067 lines

  1. /* --------------------------------------------------------------------------
  2.  * BUMPMAP.CPP
  3.  * --------------------------------------------------------------------------
  4.  * Project       : True DX6 bump mapping
  5.  *
  6.  * Purpose       : Test bump mapping on Matrox G400
  7.  *                 
  8.  * --------------------------------------------------------------------------
  9.  */
  10.  
  11.  
  12. /* --------------------------------------------------------------------------
  13.  *
  14.  * Assumes all textures are 24-bit .BMP files
  15.  *
  16.  * --------------------------------------------------------------------------
  17.  */
  18.  
  19. #define  FORCE_REFERENCERASTERIZER  FALSE                         // Change this to TRUE to use refrast
  20.  
  21. #define  INITGUID
  22.  
  23. #define  WIDTH                      640
  24. #define  HEIGHT                     480
  25. #define  BPP                        32
  26.  
  27. #define  CAMERADISTANCE             20
  28.  
  29. #define  BASEMAPFILENAME            "basemap.bmp"
  30. #define  BUMPMAPFILENAME            "bumpmap.bmp"
  31. #define  ENVMAPFILENAME             "envmap.bmp"
  32.  
  33. /* --------------------------------------------------------------------------
  34.  * General include files
  35.  */
  36. #define INITGUID
  37.  
  38. #include <stdio.h>
  39. #include <d3d.h>
  40. #include <ddraw.h>
  41.  
  42. /* --------------------------------------------------------------------------
  43.  * Global variables
  44.  */
  45.  
  46. struct MyVertexFormat
  47. {
  48.    float sx;
  49.    float sy;
  50.    float sz;
  51.    float rhw;
  52.    DWORD color;
  53.    float tu;
  54.    float tv;
  55.    float tu2;
  56.    float tv2;
  57. } Vertices[4];
  58.  
  59. // Structure that will hold the display device (HAL) selected
  60. //
  61. struct
  62. {
  63.    GUID           guid;
  64.    D3DDEVICEDESC  HWdesc;
  65.    D3DDEVICEDESC  HELdesc;
  66.    char           strDesc[256];
  67.    char           name[256];
  68.    bool           isHAL;
  69. } _3DDevice;
  70.  
  71. HWND                 hwnd;
  72. WNDCLASS             wc;
  73.  
  74. // DirectX Stuff
  75. //
  76. LPDIRECTDRAW         lpDD_temp         = NULL;
  77. LPDIRECTDRAW4        lpDD                = NULL;
  78.  
  79. LPDIRECTDRAWSURFACE4 lpDDSPrimary       = NULL;
  80. LPDIRECTDRAWSURFACE4 lpDDSBack           = NULL;
  81. LPDIRECTDRAWSURFACE4 lpDDSZ              = NULL;
  82.  
  83. LPDIRECTDRAWSURFACE4 lpDDSBaseTex      = NULL;
  84. LPDIRECT3DTEXTURE2   lpBaseTexture     = NULL;
  85.  
  86. LPDIRECTDRAWSURFACE4 lpDDSBumpTex      = NULL;
  87. LPDIRECT3DTEXTURE2   lpBumpTexture     = NULL;
  88.  
  89. LPDIRECTDRAWSURFACE4 lpDDSEnvTex       = NULL;
  90. LPDIRECT3DTEXTURE2   lpEnvTexture      = NULL;
  91.  
  92. LPDIRECTDRAWSURFACE4 lpDDSTempTex      = NULL;
  93. LPDIRECT3DTEXTURE2   lpTempTexture     = NULL;
  94.  
  95. LPDIRECTDRAWSURFACE4 lpDDSTexSystem256 = NULL;
  96. LPDIRECT3DTEXTURE2   lpTexSystem256    = NULL;
  97.  
  98. LPDIRECT3D3          lpD3D             = NULL;
  99. LPDIRECT3DDEVICE3    lpD3DDevice       = NULL;
  100. LPDIRECT3DVIEWPORT3  lpD3DViewport     = NULL;
  101.  
  102.  
  103. WORD                 MouseX, MouseY;
  104.  
  105. WORD                 Triangles[6];
  106.  
  107. FILE                 *f;
  108.  
  109. unsigned char        *MatroxLogo = NULL;
  110. unsigned char        *Bumpdata = NULL;                         // Temp buffer for bump map data
  111. unsigned char        *Bumpdata2 = NULL;
  112. unsigned char        *InBuffer, *OutBuffer;
  113.  
  114.  
  115. bool                 DoEffect = FALSE;
  116.  
  117. /* --------------------------------------------------------------------------
  118.  * Actual code starts here
  119.  */
  120.  
  121. DWORD FLOATtoDWORD( FLOAT f )
  122. {
  123.     union FLOATDWORD
  124.     {
  125.         FLOAT f;
  126.         DWORD dw;
  127.     };
  128.  
  129.     FLOATDWORD val;
  130.     val.f = f;
  131.     return val.dw;
  132. }
  133.  
  134. /* --------------------------------------------------------------------------
  135.  * Function :
  136.  *    EnumDeviceCallback
  137.  *
  138.  * Purpose  :
  139.  *    Callback that enumerates the D3D devices available
  140.  */
  141. HRESULT WINAPI EnumDeviceCallback(    LPGUID            lpGuid
  142.                                  ,    LPSTR             lpDeviceDescription
  143.                                  ,  LPSTR             lpDeviceName
  144.                                  ,  LPD3DDEVICEDESC   lpHWDesc
  145.                                  ,    LPD3DDEVICEDESC   lpHELDesc
  146.                                  ,    LPVOID            lpContext
  147.                                  )
  148. {
  149.    // Keep only hardware devices that support bump mapping
  150.    //
  151.    if( !(lpHWDesc->dwTextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP) )
  152.       return D3DENUMRET_OK;
  153.  
  154.    // Copy driver info
  155.    //
  156.    memcpy( &_3DDevice.guid, lpGuid, sizeof(GUID) );
  157.    strcpy( _3DDevice.strDesc, lpDeviceDescription );
  158.    strcpy( _3DDevice.name, lpDeviceName );
  159.     memcpy( &_3DDevice.HWdesc, lpHWDesc, sizeof(lpHWDesc) );
  160.    _3DDevice.isHAL = TRUE;
  161.  
  162.    // Bail out as soon as we found the HW device with required caps
  163.    //
  164.    return D3DENUMRET_CANCEL;
  165. }
  166.  
  167. /* --------------------------------------------------------------------------
  168.  * Function :
  169.  *    ChooseDevice
  170.  *
  171.  * Purpose  :
  172.  *    Enumerates d3d devices and picks the first HAL
  173.  */
  174. HRESULT ChooseDevice( void )
  175. {
  176.    HRESULT  err;
  177.  
  178.    _3DDevice.isHAL = FALSE;
  179.  
  180.    err = lpD3D->EnumDevices( EnumDeviceCallback, 0 );
  181.    if( err != D3D_OK )
  182.      return err;
  183.  
  184.    if( (_3DDevice.isHAL == FALSE) || FORCE_REFERENCERASTERIZER )
  185.    {
  186.       _3DDevice.guid = IID_IDirect3DRefDevice;
  187.       _3DDevice.isHAL = FALSE;
  188.    }
  189.  
  190.    return D3D_OK;
  191. }
  192.  
  193. LRESULT WINAPI WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  194. {
  195.    // Handle messages
  196.  
  197.    switch (message)
  198.    {
  199.       case WM_MOUSEMOVE:
  200.             MouseX = LOWORD( lParam );  // horizontal position of cursor 
  201.             MouseY = HIWORD( lParam );  // vertical position of cursor 
  202.             break;
  203.  
  204.       case WM_KEYDOWN:
  205.          switch( wParam )
  206.          {
  207.             case VK_ESCAPE:
  208.                PostMessage( hwnd, WM_CLOSE ,0 ,0 );
  209.                     break;
  210.  
  211.             case VK_SPACE:
  212.                DoEffect = !DoEffect;
  213.                break;
  214.  
  215.             default:      
  216.                break;
  217.          }
  218.          break;
  219.  
  220.       case WM_CLOSE:
  221.             DestroyWindow( hwnd );
  222.             break;
  223.  
  224.       case WM_DESTROY:
  225.             PostQuitMessage( 0 );
  226.             break;
  227.    }
  228.  
  229.    return DefWindowProc( hWnd, message, wParam, lParam );
  230. }
  231.  
  232. /* --------------------------------------------------------------------------
  233.  * Function :
  234.  *    Init
  235.  *
  236.  * Purpose  :
  237.  *    Initializes DD, D3D, a viewport and all associated buffers.
  238.  */
  239. BOOL Init( void )
  240. {
  241.    HINSTANCE            hInstance;
  242.      DDSURFACEDESC2       ddsd;
  243.     DDSCAPS2             ddscaps;
  244.    D3DVIEWPORT2         viewData;
  245.    HRESULT              hr;
  246.    int                  found = FALSE;
  247.  
  248. /*************************************************************************************************/
  249.  
  250.    // Set up and register window class
  251.    //
  252.    hInstance = GetModuleHandle( NULL );
  253.    wc.style = CS_NOCLOSE | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  254.    wc.lpfnWndProc = (WNDPROC)WindowProc;
  255.    wc.cbClsExtra = 0;
  256.    wc.cbWndExtra = 0;
  257.    wc.hInstance = hInstance;
  258.    wc.hIcon = NULL;
  259.    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  260.    wc.hbrBackground = NULL;
  261.    wc.lpszMenuName = "TEST";
  262.    wc.lpszClassName = "TEST";
  263.  
  264.    if( !RegisterClass( &wc ) ) { OutputDebugString( "\n\nRegisterClass failed\n\n" ); return FALSE; }
  265.  
  266.    // Create a window
  267.    //
  268.    hwnd = CreateWindowEx(  WS_EX_TOPMOST
  269.                         ,  "TEST"
  270.                         ,  "TEST"
  271.                         ,  WS_POPUP
  272.                         ,  0
  273.                         ,  0
  274.                         ,  GetSystemMetrics( SM_CXSCREEN )
  275.                         ,  GetSystemMetrics( SM_CYSCREEN )
  276.                         ,  NULL
  277.                         ,  NULL
  278.                         ,  hInstance
  279.                         ,  NULL
  280.                         );
  281.  
  282.    if( !hwnd ) { OutputDebugString( "\n\nCould not create the display window\n\n" ); return FALSE; }
  283.  
  284. /*************************************************************************************************/
  285.  
  286.     // Create DirectDraw object
  287.     //
  288.    hr = DirectDrawCreate( NULL, &lpDD_temp, NULL );
  289.  
  290.    lpDD_temp->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpDD);
  291.    lpDD_temp->Release();
  292.  
  293.    if( hr != DD_OK ) { OutputDebugString( "Could not create DD object\n" ); return FALSE; }
  294.  
  295.    // Get the D3D interface
  296.    //
  297.    hr = lpDD->QueryInterface( IID_IDirect3D3, (LPVOID *)&lpD3D );
  298.    if( hr != DD_OK ) { OutputDebugString( "\n\nUnable to get D3D interface\n\n" ); return FALSE; }
  299.  
  300.     // Choose the appropriate D3D device
  301.     //
  302.     OutputDebugString( "\n\nChoosing Device\n\n" );
  303.     ChooseDevice();
  304.  
  305.     // Get exclusive access to DD
  306.     //
  307.     hr = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  308.    if( hr != DD_OK ) { OutputDebugString("Could not get exclusive | fullscreen" ); return FALSE; }
  309.  
  310.    hr = lpDD->SetDisplayMode( WIDTH, HEIGHT, BPP, 0, 0 );
  311.    if( hr != DD_OK ) { OutputDebugString( "\n\nSetDisplayMode failed!\n\n"); return FALSE; }
  312.  
  313.    // Create flipping surfaces (front+back buffer)
  314.    //
  315.    memset( &ddsd, 0, sizeof( ddsd ) );
  316.    ddsd.dwSize             = sizeof( DDSURFACEDESC2 );
  317.    ddsd.dwFlags            = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  318.    ddsd.ddsCaps.dwCaps     = DDSCAPS_3DDEVICE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
  319.    ddsd.dwBackBufferCount  = 2;
  320.    hr = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  321.  
  322.    if( hr != DD_OK ) { OutputDebugString( "Unable to create front/back buffer\n" ); return FALSE; }
  323.  
  324. /*************************************************************************************************/   
  325.  
  326.    // Attach a Z buffer to the back buffer
  327.    //
  328.    ddscaps.dwCaps          = DDSCAPS_BACKBUFFER;
  329.    hr = lpDDSPrimary->GetAttachedSurface( &ddscaps, &lpDDSBack );
  330.  
  331.    if( hr != DD_OK ) { OutputDebugString( "Unable to get backbuffer ptr\n" ); return FALSE; }
  332.  
  333.    // Create the Z buffer
  334.    //
  335.    memset( &ddsd, 0, sizeof( ddsd ) );
  336.    ddsd.dwSize             = sizeof( DDSURFACEDESC2 );
  337.    ddsd.dwFlags            = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
  338.    ddsd.dwWidth            = WIDTH;
  339.    ddsd.dwHeight           = HEIGHT;
  340.    ddsd.ddsCaps.dwCaps     = DDSCAPS_ZBUFFER;
  341.  
  342.    if( _3DDevice.isHAL )
  343.       ddsd.ddsCaps.dwCaps |=  DDSCAPS_VIDEOMEMORY;
  344.    else
  345.       ddsd.ddsCaps.dwCaps |=  DDSCAPS_SYSTEMMEMORY;
  346.  
  347.    ddsd.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
  348.    ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
  349.    ddsd.ddpfPixelFormat.dwZBufferBitDepth = 16;
  350.    ddsd.ddpfPixelFormat.dwZBitMask = 0xffff;
  351.  
  352.    hr = lpDD->CreateSurface( &ddsd, &lpDDSZ, NULL );
  353.    if( hr != DD_OK ) { OutputDebugString( "\n\nUnable to create Z surface\n\n" ); return FALSE; }
  354.  
  355.    // Attach the Z buffer
  356.    //
  357.    hr = lpDDSBack->AddAttachedSurface( lpDDSZ );
  358.    if( hr != DD_OK ) { OutputDebugString( "\n\nUnable to attach Z surface\n\n" ); return FALSE; }      
  359.  
  360.    OutputDebugString("\n\nInit Direct3D stuff\n\n");
  361.  
  362.    // Create the D3D device with the guid we selected previously
  363.    //
  364.    OutputDebugString( "\n\nCreating Device\n\n" );
  365.    hr = lpD3D->CreateDevice( _3DDevice.guid, lpDDSBack, &lpD3DDevice, NULL );
  366.    if( hr != DD_OK ) { OutputDebugString( "\n\nUnable to create lpd3dDevice\n\n" ); return FALSE; }
  367.  
  368. /*************************************************************************************************/    
  369.  
  370.    // Setup the viewport
  371.    //
  372.    memset( &viewData, 0, sizeof( D3DVIEWPORT2 ) );
  373.    viewData.dwSize         = sizeof( D3DVIEWPORT2 );
  374.    viewData.dwX            = 0;
  375.    viewData.dwY            = 0;
  376.    viewData.dwWidth        = WIDTH;
  377.    viewData.dwHeight       = HEIGHT;
  378.    viewData.dvClipX        = -1.0f;
  379.    viewData.dvClipY        = 1.0f;
  380.    viewData.dvClipWidth    = 2.0f;
  381.    viewData.dvClipHeight   = 2.0f;
  382.    viewData.dvMinZ         = 0.0f;
  383.    viewData.dvMaxZ         = 1.0f;
  384.  
  385.    // Create viewport
  386.    //
  387.    OutputDebugString( "\n\nCreating Viewport\n\n" );
  388.    hr = lpD3D->CreateViewport( &lpD3DViewport, NULL );
  389.    if( hr != DD_OK ) { OutputDebugString( "\n\nCreateViewport failed\n\n" ); return FALSE; }
  390.  
  391.    // Add viewport to device
  392.    //
  393.    OutputDebugString( "\n\nAdding Viewport\n\n" );
  394.    hr = lpD3DDevice->AddViewport( lpD3DViewport );
  395.    if( hr != D3D_OK ) { OutputDebugString( "\nAddViewport failed\n\n" ); return FALSE; }
  396.  
  397.    OutputDebugString( "\n\nSetting Viewport2\n\n" );
  398.    hr = lpD3DViewport->SetViewport2( &viewData );
  399.    if( hr != D3D_OK ) { OutputDebugString( "\n\nSetViewport2 failed\n\n" ); return FALSE; }
  400.  
  401.    OutputDebugString("Setting Current Viewport\n");
  402.    hr = lpD3DDevice->SetCurrentViewport(lpD3DViewport);
  403.    if( hr != D3D_OK ) { OutputDebugString( "\n\nSetCurrentViewport failed\n\n" ); return FALSE; }
  404.  
  405. /*************************************************************************************************/
  406.  
  407.    // Create a texture surface in system memory (scratch texture used to load)
  408.    //
  409.    memset( &ddsd, 0, sizeof( ddsd ) );
  410.    ddsd.dwSize             = sizeof( DDSURFACEDESC2 );
  411.    ddsd.dwFlags            = DDSD_WIDTH
  412.                            | DDSD_HEIGHT
  413.                            | DDSD_CAPS
  414.                            | DDSD_PIXELFORMAT
  415.                            ;
  416.  
  417.    ddsd.ddpfPixelFormat.dwSize            = sizeof( DDPIXELFORMAT );
  418.    ddsd.ddpfPixelFormat.dwFlags           = DDPF_RGB;
  419.    ddsd.ddpfPixelFormat.dwFourCC          = 0;
  420.    ddsd.ddpfPixelFormat.dwRGBBitCount     = 32;
  421.    ddsd.ddpfPixelFormat.dwRBitMask        = 0x00FF0000;
  422.    ddsd.ddpfPixelFormat.dwGBitMask        = 0x0000FF00;
  423.    ddsd.ddpfPixelFormat.dwBBitMask        = 0x000000FF;
  424.    ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
  425.  
  426.    ddsd.ddsCaps.dwCaps  = DDSCAPS_TEXTURE
  427.                         | DDSCAPS_SYSTEMMEMORY
  428.                         ;
  429.  
  430.    ddsd.dwWidth            = 256;
  431.    ddsd.dwHeight           = 256;
  432.    hr = lpDD->CreateSurface( &ddsd, &lpDDSTexSystem256, NULL );
  433.    hr = lpDDSTexSystem256->QueryInterface( IID_IDirect3DTexture2, (LPVOID *) &lpTexSystem256 );
  434.  
  435.    // Create the bump map surface.
  436.    //
  437.    memset( &ddsd, 0, sizeof(ddsd) );
  438.  
  439.    ddsd.dwSize             = sizeof(ddsd);
  440.    ddsd.dwFlags            = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
  441.    ddsd.dwWidth            = 256;
  442.    ddsd.dwHeight           = 256;
  443.    ddsd.ddsCaps.dwCaps     = DDSCAPS_TEXTURE;
  444.  
  445.    if( _3DDevice.isHAL )
  446.       ddsd.ddsCaps.dwCaps |=  DDSCAPS_VIDEOMEMORY;
  447.    else
  448.       ddsd.ddsCaps.dwCaps |=  DDSCAPS_SYSTEMMEMORY;
  449.  
  450.    ddsd.ddpfPixelFormat.dwSize                  = sizeof(DDPIXELFORMAT);
  451.    ddsd.ddpfPixelFormat.dwFlags                 = DDPF_BUMPDUDV;
  452.    ddsd.ddpfPixelFormat.dwBumpBitCount          = 16;
  453.    ddsd.ddpfPixelFormat.dwBumpDuBitMask         = 0x000000ff;
  454.    ddsd.ddpfPixelFormat.dwBumpDvBitMask         = 0x0000ff00;
  455.    ddsd.ddpfPixelFormat.dwBumpLuminanceBitMask  = 0x00000000;
  456.  
  457.    hr = lpDD->CreateSurface( &ddsd, &lpDDSBumpTex, NULL );
  458.    hr = lpDDSBumpTex->QueryInterface( IID_IDirect3DTexture2, (VOID**)&lpBumpTexture );
  459.  
  460.  
  461.    // Set a couple of default renderstates
  462.    //
  463.    lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZENABLE,       TRUE );
  464.    lpD3DDevice->SetRenderState( D3DRENDERSTATE_CULLMODE,      D3DCULL_CW );
  465.    lpD3DDevice->SetRenderState( D3DRENDERSTATE_SHADEMODE,     D3DSHADE_GOURAUD );
  466.    lpD3DDevice->SetRenderState( D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE );
  467.    lpD3DDevice->SetRenderState( D3DRENDERSTATE_DITHERENABLE,  TRUE );
  468.  
  469.  
  470.    ShowCursor( FALSE );
  471.  
  472.    OutputDebugString( "\n\nInitialization Complete!\n\n" );
  473.  
  474.    return TRUE;
  475. }
  476.  
  477. void ReleaseAll( void )
  478. {
  479.      if( lpDD )
  480.     {
  481.         if( lpD3D )
  482.       {
  483.          if( lpD3DDevice )
  484.             lpD3DDevice->Release();
  485.  
  486.          if( lpD3DViewport )
  487.             lpD3DViewport->Release();
  488.  
  489.          lpD3D->Release();
  490.          lpD3D = NULL;
  491.       }
  492.  
  493.       if( lpDDSPrimary )
  494.         {
  495.             lpDDSPrimary->Release();
  496.             lpDDSPrimary = NULL;
  497.             lpDDSBack     = NULL;
  498.          lpDDSZ = NULL;
  499.         }
  500.  
  501.       if( lpDDSBaseTex )
  502.       {
  503.          lpDDSBaseTex->Release();
  504.          lpDDSBaseTex = NULL;
  505.       }
  506.  
  507.       if( lpDDSBumpTex )
  508.       {
  509.          lpDDSBumpTex->Release();
  510.          lpDDSBumpTex = NULL;
  511.       }
  512.  
  513.       if( lpDDSEnvTex )
  514.       {
  515.          lpDDSEnvTex->Release();
  516.          lpDDSEnvTex = NULL;
  517.       }
  518.  
  519.       if( lpDDSTempTex )
  520.       {
  521.          lpDDSTempTex->Release();
  522.          lpDDSTempTex = NULL;
  523.       }
  524.  
  525.       if( lpDDSTexSystem256 )
  526.       {
  527.          lpDDSTexSystem256->Release();
  528.          lpDDSTexSystem256 = NULL;
  529.       }
  530.  
  531.         lpDD->Release();
  532.         lpDD = NULL;
  533.  
  534.     }
  535.  
  536.    ShowCursor( TRUE );
  537. }
  538.  
  539. /* --------------------------------------------------------------------------
  540.  * Function :
  541.  *    LoadBMP
  542.  *
  543.  * Purpose  :
  544.  *    Loads a 24-bit .bmp file onto 32-bit texture surface.
  545.  *
  546.  * Assumes a square texture .bmp (Size x Size)
  547.  */
  548. void LoadBMP( char *filename, int Size )
  549. {
  550.    int               x,y;
  551.    unsigned char     r,g,b;
  552.    BYTE              *pSurface;
  553.    DDSURFACEDESC2    ddsd;
  554.    FILE              *f;
  555.  
  556.    f = fopen( filename,"rb" );
  557.    if( f == NULL )
  558.       return;
  559.  
  560.    fseek( f, -Size*Size*3-2, SEEK_END );
  561.  
  562.    memset( &ddsd, 0, sizeof( ddsd ) );
  563.    ddsd.dwSize = sizeof( ddsd );
  564.  
  565.    // Lock the surface to access it directly
  566.    //
  567.    switch( Size )
  568.    {
  569.       case 256 : lpDDSTexSystem256->Lock( NULL, &ddsd, 0, NULL ); break;
  570.    }
  571.  
  572.    // Copy the bitmap data to the surface
  573.    //
  574.    for(y = Size-1; y >= 0; y-- )
  575.    {
  576.       pSurface = (BYTE *) ((BYTE *)ddsd.lpSurface + y*ddsd.lPitch);
  577.       
  578.       for( x = 0; x < Size; x++ )
  579.       {
  580.          fread( &r, 1, 1, f );
  581.          fread( &g, 1, 1, f );
  582.          fread( &b, 1, 1, f );
  583.          *pSurface++ = r;
  584.          *pSurface++ = g;
  585.          *pSurface++ = b;
  586.          *pSurface++ = 255;   // Set alpha to anything
  587.       }
  588.    }
  589.  
  590.    fclose(f);
  591.  
  592.    switch( Size )
  593.    {
  594.       case 256 : lpDDSTexSystem256->Unlock( NULL ); break;
  595.    }
  596.  
  597. }
  598.  
  599. /* --------------------------------------------------------------------------
  600.  * Function :
  601.  *    LoadBMPToRawBuffer
  602.  *
  603.  * Purpose  :
  604.  *    Loads a 24-bit .bmp file onto 8-bit raw buffer
  605.  *
  606.  * Assumes a square texture .bmp (Size x Size)
  607.  */
  608. void LoadBMPToRawBuffer( char *filename, int Size, unsigned char *Buffer )
  609. {
  610.    int               x, y;
  611.    unsigned char     r, g, b;
  612.    FILE              *f;
  613.  
  614.    f = fopen( filename, "rb" );
  615.    if( f == NULL )
  616.       return;
  617.  
  618.    fseek( f, -Size*Size*3-2, SEEK_END );
  619.  
  620.    for( y = Size-1; y >= 0; y-- )
  621.    {
  622.       for( x = 0; x < Size; x++ )
  623.       {
  624.          fread( &r, 1, 1, f );
  625.          fread( &g, 1, 1, f );
  626.          fread( &b, 1, 1, f );
  627.  
  628.          Buffer[(y*Size+x+0)] = r;
  629.       }
  630.    }
  631.  
  632.    fclose(f);
  633. }
  634.  
  635. /* --------------------------------------------------------------------------
  636.  * Function :
  637.  *    CreateTexture
  638.  *
  639.  * Purpose  :
  640.  *    Creates a texture
  641.  *
  642.  */
  643. LPDIRECT3DTEXTURE2 CreateTexture( LPDIRECTDRAWSURFACE4 *DDSTex, int TextureSize )
  644. {
  645.    DDSURFACEDESC2       ddsd;
  646.    LPDIRECT3DTEXTURE2   *t;
  647.  
  648.    t = (LPDIRECT3DTEXTURE2 *)malloc( sizeof(LPDIRECT3DTEXTURE2) );
  649.  
  650.    // Create a texture surface in video memory
  651.    //
  652.    memset( &ddsd, 0, sizeof(ddsd) );
  653.    ddsd.dwSize             = sizeof( DDSURFACEDESC2 );
  654.    ddsd.dwFlags            = DDSD_WIDTH
  655.                            | DDSD_HEIGHT
  656.                            | DDSD_CAPS
  657.                            | DDSD_PIXELFORMAT
  658.                            ;
  659.  
  660.    ddsd.dwWidth            = TextureSize;
  661.    ddsd.dwHeight           = TextureSize;
  662.    ddsd.ddsCaps.dwCaps     = DDSCAPS_TEXTURE
  663.                            | DDSCAPS_ALLOCONLOAD
  664.                            ;
  665.  
  666.    ddsd.ddpfPixelFormat.dwSize            = sizeof( DDPIXELFORMAT );
  667.    ddsd.ddpfPixelFormat.dwFlags           = DDPF_RGB;
  668.    ddsd.ddpfPixelFormat.dwFourCC          = 0;
  669.    ddsd.ddpfPixelFormat.dwRGBBitCount     = 32;
  670.    ddsd.ddpfPixelFormat.dwRBitMask        = 0x00FF0000;
  671.    ddsd.ddpfPixelFormat.dwGBitMask        = 0x0000FF00;
  672.    ddsd.ddpfPixelFormat.dwBBitMask        = 0x000000FF;
  673.    ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
  674.  
  675.    if( _3DDevice.isHAL )
  676.       ddsd.ddsCaps.dwCaps |=  DDSCAPS_VIDEOMEMORY;
  677.    else
  678.       ddsd.ddsCaps.dwCaps |=  DDSCAPS_SYSTEMMEMORY;
  679.  
  680.    lpDD->CreateSurface( &ddsd, DDSTex, NULL );
  681.  
  682.    (*DDSTex)->QueryInterface( IID_IDirect3DTexture2, (LPVOID *) t );
  683.    
  684.    return *t;
  685. }
  686.  
  687. /* --------------------------------------------------------------------------
  688.  * Function :
  689.  *    TransformVertices
  690.  *
  691.  * Purpose  :
  692.  *    Prepare vertex data to be sent to renderer.  Calculate UV's for envmap
  693.  *
  694.  */
  695. void TransformVertices( void )
  696. {
  697.    // Set up vertices
  698.    //
  699.    Vertices[0].sx = 0.0f;
  700.    Vertices[0].sy = 0.0f;
  701.    Vertices[0].sz = 1.0f;
  702.    Vertices[0].rhw = 1.0f;
  703.    Vertices[0].tu = 0.0f;
  704.    Vertices[0].tv = 0.0f;
  705.  
  706.    Vertices[1].sx = 0.0f;
  707.    Vertices[1].sy = 255.0f;
  708.    Vertices[1].sz = 1.0f;
  709.    Vertices[1].rhw = 1.0f;
  710.    Vertices[1].tu = 0.0f;
  711.    Vertices[1].tv = 1.0f;
  712.  
  713.    Vertices[2].sx = 255.0f;
  714.    Vertices[2].sy = 255.0f;
  715.    Vertices[2].sz = 1.0f;
  716.    Vertices[2].rhw = 1.0f;
  717.    Vertices[2].tu = 1.0f;
  718.    Vertices[2].tv = 1.0f;
  719.  
  720.    Vertices[3].sx = 255.0f;
  721.    Vertices[3].sy = 0.0f;
  722.    Vertices[3].sz = 1.0f;
  723.    Vertices[3].rhw = 1.0f;
  724.    Vertices[3].tu = 1.0f;
  725.    Vertices[3].tv = 0.0f;
  726.  
  727.  
  728.    // Calculate U,V's for the environment map
  729.    //
  730.    for( int i = 0; i < 4; i++ )
  731.    {
  732.       // Just a simple planar mapping
  733.       // Should use transformed vertex normals to do a spherical mapping instead.
  734.       //
  735.       Vertices[i].tu2 = (Vertices[i].sx - WIDTH/2)/WIDTH + (float)(WIDTH-MouseX)/WIDTH;
  736.       Vertices[i].tv2 = (Vertices[i].sy - HEIGHT/2)/HEIGHT + (float)(HEIGHT-MouseY)/HEIGHT;
  737.       Vertices[i].color = D3DRGB(1.0f,1.0f,1.0f);
  738.    }
  739.  
  740.    // Set up triangles
  741.    //
  742.    Triangles[0] = 0;
  743.    Triangles[1] = 1;
  744.    Triangles[2] = 2;
  745.  
  746.    Triangles[3] = 0;
  747.    Triangles[4] = 2;
  748.    Triangles[5] = 3;
  749.  
  750. }
  751.  
  752. BOOL Render( void )
  753. {
  754.    HRESULT  err;
  755.      DDBLTFX              ddbltfx;
  756.  
  757.    if( lpDDSBack->IsLost() )
  758.       lpDDSBack->Restore();
  759.  
  760.    if( lpDDSZ->IsLost() )
  761.       lpDDSZ->Restore();
  762.  
  763.    // This is where the rendering is taking place
  764.  
  765.     memset( &ddbltfx, 0, sizeof(ddbltfx) );
  766.    ddbltfx.dwSize = sizeof( DDBLTFX );
  767.     ddbltfx.dwFillColor = 0;
  768.    err = lpDDSBack->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx );
  769.  
  770.    memset( &ddbltfx, 0, sizeof(ddbltfx) );
  771.    ddbltfx.dwSize = sizeof( DDBLTFX );
  772.     ddbltfx.dwFillDepth = 0xFFFF;
  773.    err = lpDDSZ->Blt( NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &ddbltfx );
  774.  
  775.    // Update back buffer
  776.    //
  777.    err = lpD3DDevice->BeginScene();
  778.    if(err != DD_OK)
  779.    {
  780.       OutputDebugString("\nBeginScene() Failed!\n");
  781.       return FALSE;
  782.    }
  783.  
  784.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP );
  785.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );
  786.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR );
  787.  
  788.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP );
  789.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTFG_LINEAR );
  790.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTFN_LINEAR );
  791.  
  792.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_ADDRESS, D3DTADDRESS_WRAP );
  793.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTFG_LINEAR );
  794.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTFN_LINEAR );
  795.  
  796.  
  797.    // Base Texture
  798.    //
  799.    lpD3DDevice->SetTexture( 0, lpBaseTexture );
  800.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  801.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
  802.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  803.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  804.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  805.    lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  806.  
  807.    // Bump Texture
  808.    //
  809.    lpD3DDevice->SetTexture( 1, lpBumpTexture );
  810.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
  811.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP );
  812.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  813.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
  814.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_BUMPENVMAT00, FLOATtoDWORD(1.0f) );
  815.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_BUMPENVMAT01, FLOATtoDWORD(0.0f) );
  816.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_BUMPENVMAT10, FLOATtoDWORD(0.0f) );
  817.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_BUMPENVMAT11, FLOATtoDWORD(1.0f) );
  818.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_BUMPENVLSCALE, FLOATtoDWORD(1.0f) );
  819.    lpD3DDevice->SetTextureStageState( 1, D3DTSS_BUMPENVLOFFSET, FLOATtoDWORD(0.0f) );
  820.  
  821.    // Environment Texture
  822.    //
  823.    lpD3DDevice->SetTexture( 2, lpEnvTexture );
  824.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP );
  825.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 1 );
  826.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_ADD );
  827.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  828.    lpD3DDevice->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_CURRENT );
  829.  
  830.    // Render the triangles!
  831.    //
  832.    err = lpD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST
  833.                                           , D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2
  834.                                           , (LPVOID)Vertices
  835.                                           , 4
  836.                                           , (LPWORD)Triangles
  837.                                           , 6
  838.                                           , D3DDP_DONOTCLIP
  839.                                           );
  840.    if( err != D3D_OK )
  841.    {
  842.       OutputDebugString( "\n\nDrawIndexedPrimitive() Failed!\n\n" );
  843.       return FALSE;
  844.    }
  845.  
  846.    if( lpD3DDevice->EndScene() != D3D_OK )
  847.    {
  848.       OutputDebugString( "\nEndScene() Failed!\n" );
  849.       return FALSE;
  850.    }
  851.  
  852.    // Flip
  853.    //
  854.    lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
  855.  
  856.    return TRUE;
  857. }
  858.  
  859. void DoSomeCoolEffect( void )
  860. {
  861.    int   i, j;
  862.  
  863.    // Put some random raindrops
  864.    for( i = 0; i < 50; i++ )
  865.    {
  866.       int   x, y;
  867.       x = rand() % 254 + 1;
  868.       y = rand() % 254 + 1;
  869.       InBuffer[ y*256 + x ] = rand() % 255;
  870.    }
  871.  
  872.    // Update OutBuffer
  873.    //
  874.    for( i = 1; i < 255; i++ )
  875.    {
  876.       for( j = 1; j < 255; j++ )
  877.       {
  878.          int   index;
  879.  
  880.          index = j*256 + i;
  881.          OutBuffer[index] = (InBuffer[index-1] + InBuffer[index-256] + InBuffer[index+1] + InBuffer[index+256]) >> 2;
  882.       }
  883.    }
  884.  
  885. }
  886.  
  887. /* --------------------------------------------------------------------------
  888.  * Function :
  889.  *    InitBumpmap
  890.  *
  891.  * Purpose  :
  892.  *    Create a bump map texture and fill its content converted from raw RGB
  893.  *    to DX6 BUMPDUDV format
  894.  *
  895.  */
  896. void InitBumpmap( unsigned char *Buffer, int TextureSize )
  897. {
  898.    // Create the bump map surface.
  899.    //
  900.    DDSURFACEDESC2       ddsd;
  901.  
  902.    // Calculate displacement map for the bumpmap
  903.    // Fill the bits of the new texture surface with bits from a private format.
  904.    //
  905.    ddsd.dwSize = sizeof( ddsd );
  906.    lpDDSBumpTex->Lock( NULL, &ddsd, DDLOCK_WAIT , NULL );
  907.  
  908.    for( DWORD y = 0; y < ddsd.dwHeight; y++ )
  909.    {
  910.       BYTE* pDst = (BYTE*)ddsd.lpSurface + y*ddsd.lPitch;
  911.  
  912.       for( DWORD x = 0; x < ddsd.dwWidth; x++ )
  913.       {
  914.          LONG  v00, v01, v10;
  915.  
  916.          v00 = Buffer[(y*TextureSize+x)];          // Get the current pixel
  917.  
  918.          if( x == ddsd.dwWidth-1 )
  919.             v01 = Buffer[(y*TextureSize+x)];       // and the pixel to the right
  920.          else
  921.             v01 = Buffer[(y*TextureSize+x+1)];     // and the pixel to the right
  922.  
  923.          if( y == ddsd.dwHeight-1 )
  924.             v10 = Buffer[((y)*TextureSize+x)];     // and the pixel one line below.
  925.          else
  926.             v10 = Buffer[((y+1)*TextureSize+x)];   // and the pixel one line below.
  927.  
  928.          LONG iDu = v00 - v01;                     // The delta-u bump value
  929.          LONG iDv = v00 - v10;                     // The delta-v bump value
  930.  
  931.          *pDst++ = (BYTE)iDu;
  932.          *pDst++ = (BYTE)iDv;
  933.       }
  934.  
  935.    }
  936.  
  937.    lpDDSBumpTex->Unlock(0);
  938. }
  939.  
  940. /* --------------------------------------------------------------------------
  941.  * Function :
  942.  *    WinMain()
  943.  *
  944.  * Purpose  :
  945.  *    Program entry point.
  946.  */
  947. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
  948. {
  949.    MSG      msg;
  950.    BOOL     err;
  951.    int      FrameNo = 0;
  952.  
  953.    // Initialize D3D
  954.    //
  955.    if( !Init() )
  956.    {
  957.       ReleaseAll();
  958.       OutputDebugString("\n\nError occured while initializing! :(\n\n");
  959.       return -1;
  960.    }
  961.  
  962.    // Create all textures needed by the application
  963.    //
  964.    lpBaseTexture = CreateTexture( &lpDDSBaseTex, 256 );
  965.    LoadBMP( BASEMAPFILENAME, 256 );
  966.    lpBaseTexture->Load( lpTexSystem256 );
  967.  
  968.    // Load the bump map file to a buffer
  969.    //
  970.    Bumpdata = (unsigned char *)malloc( 256*256 );
  971.    Bumpdata2 = (unsigned char *)malloc( 256*256 );
  972.    MatroxLogo = (unsigned char *)malloc( 256*256 );
  973.  
  974.    LoadBMPToRawBuffer( BUMPMAPFILENAME, 256 , MatroxLogo );
  975.  
  976.    // Convert the RGB (assumes a grayscale image) to DX6 Bump format
  977.    //
  978.    memset( Bumpdata, 0, 256*256 );
  979.    memset( Bumpdata2, 0, 256*256 );
  980.  
  981.    InitBumpmap( Bumpdata, 256 );
  982.  
  983.    // Environment map texture
  984.    //
  985.    lpEnvTexture = CreateTexture( &lpDDSEnvTex, 256 );
  986.    LoadBMP( ENVMAPFILENAME, 256 );
  987.    lpEnvTexture->Load( lpTexSystem256 );
  988.  
  989.  
  990.    InBuffer = Bumpdata;
  991.    OutBuffer = Bumpdata2;
  992.  
  993.    // Windoze message pump
  994.    //
  995.    while( TRUE )
  996.    {
  997.       if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
  998.       {
  999.          // Message pending. If it's QUIT then exit the message loop.
  1000.          if (WM_QUIT == msg.message)
  1001.          {
  1002.              break;
  1003.          }
  1004.  
  1005.          // Otherwise, process the message.
  1006.          else
  1007.          {
  1008.              TranslateMessage(&msg);
  1009.              DispatchMessage(&msg);
  1010.          }
  1011.       }
  1012.       else
  1013.       {
  1014.          // Render the scene
  1015.          //
  1016.          TransformVertices();
  1017.  
  1018.          FrameNo++;
  1019.          if( FrameNo > 200 )
  1020.          {
  1021.             FrameNo = 0;
  1022.  
  1023.             // Copy the Matrox logo to the InBuffer
  1024.             
  1025.             for( int i = 0; i < 256; i++ )
  1026.             {
  1027.                for( int j = 0; j < 256; j++ )
  1028.                {
  1029.                   unsigned char pixel;
  1030.                   int index;
  1031.  
  1032.                   index = i*256+j;
  1033.                   pixel = MatroxLogo[index];
  1034.  
  1035.                   if( pixel )
  1036.                      InBuffer[index] = pixel;
  1037.                }
  1038.             }
  1039.          }
  1040.  
  1041.          // Do Some Cool Effect
  1042.          if( DoEffect )
  1043.             DoSomeCoolEffect();
  1044.          else
  1045.             memcpy( OutBuffer, MatroxLogo, 256*256 );
  1046.          InitBumpmap( OutBuffer, 256 );
  1047.  
  1048.          // Swap the buffers used for the rain effect
  1049.          //
  1050.          unsigned char *temp;
  1051.          temp = InBuffer;
  1052.          InBuffer = OutBuffer;
  1053.          OutBuffer = temp;
  1054.  
  1055.          err = Render();
  1056.  
  1057.          if( err == FALSE )
  1058.             goto End;
  1059.       }
  1060.    }
  1061.  
  1062. End:
  1063.    ReleaseAll();
  1064.  
  1065.    return 0;
  1066. }
  1067.